package com.agileai.hotweb.domain;

import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.apache.commons.beanutils.BeanUtilsBean;

import com.agileai.util.StringUtil;

public class TreeBuilder {
	@SuppressWarnings("rawtypes")
	private List treeRecords = null;
    private String rootId = null;
    private String idKey = null;
    private String nameKey = null;
    private String pidKey = null;
    private String typeKey = null;
    private Map<String,String> idnamePair = new HashMap<String,String>();
    private List<String> excludeIds = new ArrayList<String>();
    private TreeModel rootTreeModel = null;
    private boolean isPojoList = false;
    
    public TreeModel getRootTreeModel() {
		return rootTreeModel;
	}
	@SuppressWarnings("rawtypes")
	public TreeBuilder(List treeRecords,String idKey,String nameKey,String pidKey){
        this.treeRecords = treeRecords;
        this.idKey = idKey;
        this.nameKey = nameKey;
        this.pidKey = pidKey;
    }
	public void setRootId(String rootId) {
		this.rootId = rootId;
	}
	public void setTypeKey(String typeKey) {
		this.typeKey = typeKey;
	}
	@SuppressWarnings("rawtypes")
	public TreeModel buildTreeModel(){
		rootTreeModel = new TreeModel();
		HashMap row = getRootRow();
		if (row != null){
			rootTreeModel.processRow(row);
			String id = String.valueOf(row.get(idKey));
			String name = String.valueOf(row.get(nameKey));
			idnamePair.put(id,name);
			rootTreeModel.setId(id);
			rootTreeModel.setName(name);
			if (!StringUtil.isNullOrEmpty(typeKey)){
				String type = String.valueOf(row.get(typeKey));
				rootTreeModel.setType(type);
			}
			rootTreeModel.getFullTreeMap().put(id, rootTreeModel);
			buildTree(rootTreeModel);
		}
		return rootTreeModel;
	}
	@SuppressWarnings("rawtypes")
	private void buildTree(TreeModel treeModel){
		for (int i=0;i < treeRecords.size();i++){
    		Object bean = treeRecords.get(i);
    		HashMap row = null;
    		if (this.isPojoList){
    			row = this.getPropertyMap(bean);
    		}else{
    			row = (HashMap)bean;        			
    		}
			String id = String.valueOf(row.get(idKey));
			if (this.excludeIds.contains(id)){
				continue;
			}
			String name = String.valueOf(row.get(nameKey));
			String pid = String.valueOf(row.get(pidKey));
			if (treeModel.getId().equals(pid)){
				TreeModel curTreeModel = new TreeModel();
				curTreeModel.setId(id);
				curTreeModel.setName(name);
				idnamePair.put(id,name);
				rootTreeModel.getDescendantIds().add(id);
				if (!StringUtil.isNullOrEmpty(typeKey)){
					String type = String.valueOf(row.get(typeKey));
					curTreeModel.setType(type);
				}
				curTreeModel.processRow(row);
				treeModel.addChild(curTreeModel);
				curTreeModel.setParent(treeModel);
				rootTreeModel.getFullTreeMap().put(id, curTreeModel);
				
				buildTree(curTreeModel);
			}
		}
	}
	@SuppressWarnings("rawtypes")
	private HashMap getRootRow(){
		HashMap result = null;
        if (rootId == null){
        	Iterator iter = treeRecords.iterator();
        	while(iter.hasNext()){
        		Object bean = iter.next();
        		HashMap row = null;
        		if (this.isPojoList){
        			row = this.getPropertyMap(bean);
        		}else{
        			row = (HashMap)bean;        			
        		}
                String parentId = String.valueOf(row.get(pidKey));
                if (StringUtil.isNullOrEmpty(parentId)){
                    result = row;
                    break;
                }
        	}
        }
        else{
        	Iterator iter = treeRecords.iterator();
        	while(iter.hasNext()){
        		Object bean = iter.next();
        		HashMap row = null;
        		if (this.isPojoList){
        			row = this.getPropertyMap(bean);        			
        		}else{
        			row = (HashMap)bean;
        		}
                String parentId = String.valueOf(row.get(idKey));
                if (rootId.equals(parentId)){
                    result = row;
                    break;
                }
        	}
        }
        return result;
    }
	public Map<String, String> getIdnamePair() {
		return idnamePair;
	}
	public List<String> getExcludeIds() {
		return excludeIds;
	}
	public void setPojoList(boolean isPojoList) {
		this.isPojoList = isPojoList;
	}
	@SuppressWarnings("rawtypes")
	private HashMap getPropertyMap(Object bean){
		HashMap beanProperties = new HashMap();
		try {
			beanProperties = (HashMap)BeanUtilsBean.getInstance().describe(bean);
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		}
		return beanProperties;
	}
}
